package com.nineclock.auth.config;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.nineclock.auth.intergration.entity.IntergrationAuthenticationEntity;
import com.nineclock.auth.intergration.processor.AuthenticationProcessor;
import com.nineclock.auth.intergration.threadlocal.IntergrationAuthenticationHolder;
import com.nineclock.auth.intergration.threadlocal.UserHolder;
import com.nineclock.common.constant.NcConstant;
import com.nineclock.common.entity.NcAuthority;
import com.nineclock.common.entity.UserInfo;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.system.dto.SysCompanyUserDTO;
import com.nineclock.system.dto.SysRoleDTO;
import com.nineclock.system.dto.SysUserDTO;
import com.nineclock.system.feign.SysUserFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Optional;

/**
 * 自定义用户详情类
 */
@Component
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private List<AuthenticationProcessor> processorList;

    @Autowired
    private SysUserFeign sysUserFeign;

    //明文密码为
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //从ThreadLocal中获取参数
        IntergrationAuthenticationEntity entity = IntergrationAuthenticationHolder.get();

        //获取AuthType
        String authType = entity.getAuthType();

        //根据AuthType选择认证处理器
        AuthenticationProcessor processor = this.chooseAuthenticationProcessor(entity);

        //校验
        if(processor == null){
            throw new NcException(ResponseEnum.SERVER_ERROR);
        }

        //调用认证处理器的认证方法
        SysUserDTO userDTO = processor.authenticate(entity); // userDTO 中封装的 是用户基本信息 ;

        //UserInfo只包含基本的用户数据 , 存放在JWT令牌中
        UserInfo userInfo = BeanHelper.copyProperties(userDTO, UserInfo.class);




        // --------------------------> 认证功能完善
        //判定是否是PC端认证 ---> pc_client
        String clientId = entity.getAuthParameter("client_id");
        String companyId = entity.getAuthParameter("company_id");

        //如果是PC端
        if(NcConstant.PC_CLIENT.equals(clientId)){//PC端认证

            //根据用户ID查询该用户对应的企业员工数据
            List<SysCompanyUserDTO> companyUserDTOList = sysUserFeign.queryCompanyUser(userDTO.getId(), null).getData();
            if(CollectionUtil.isEmpty(companyUserDTOList)){//没有对应的员工
                throw new NcException(ResponseEnum.USER_NOT_JOIN_COMPANY);
            }

            //判定该用户是否是管理员 ----------> ROLE_ADMIN_xxx
            for (SysCompanyUserDTO companyUserDTO : companyUserDTOList) {
                Boolean isAdmin = isAdmin(companyUserDTO);//ROLE_ADMIN_XXX
                if(!isAdmin){ //不是企业管理员
                    throw new NcException(ResponseEnum.USER_NOT_COMPANY_ADMIN);
                }
            }

            //关联的企业只有一个 , 封装用户的关联的企业信息 , 权限信息
            if(companyUserDTOList.size() == 1) {
                wrapperUserInfo(userInfo, companyUserDTOList.get(0));
            }


            //如果选择了企业....
            if(StrUtil.isNotEmpty(companyId)){
                List<SysCompanyUserDTO> userDTOS = sysUserFeign.queryCompanyUser(userDTO.getId(), Long.valueOf(companyId)).getData();
                if(CollectionUtil.isNotEmpty(userDTOS)){
                    wrapperUserInfo(userInfo, userDTOS.get(0));
                }
            }

        }else { //APP端
            //判定是否传递companyId, 如果未传递 , 获取最后一次登录的企业ID
            if(StrUtil.isEmpty(companyId)){
                companyId = String.valueOf(userDTO.getLastLoginCompanyId());
            }

            //根据userId, companyId查询关联的员工信息
            List<SysCompanyUserDTO> userDTOList = sysUserFeign.queryCompanyUser(userDTO.getId(), Long.valueOf(companyId)).getData();

            //数据封装
            if(CollectionUtil.isNotEmpty(userDTOList)){
                wrapperUserInfo(userInfo, userDTOList.get(0));
            }
        }


        UserHolder.set(userInfo);// 存储UserInfo到ThreadLocal
        //组装数据并返回
        User loginUser = new User(JSONUtil.toJsonStr(userInfo), userDTO.getPassword(), userInfo.getGrantedAuthorities());
        return loginUser;
    }


    /**
     * 在Userinfo中封装用户关联的企业信息
     * @param userInfo
     * @param sysCompanyUserDTO
     */
    private void wrapperUserInfo(UserInfo userInfo, SysCompanyUserDTO sysCompanyUserDTO) {
        userInfo.setCompanyId(sysCompanyUserDTO.getCompanyId());
        userInfo.setCompanyName(sysCompanyUserDTO.getCompanyName());
        userInfo.setDepartmentId(sysCompanyUserDTO.getDepartmentId());
        userInfo.setDepartmentName(sysCompanyUserDTO.getDepartmentName());
        userInfo.setCompanyUserId(sysCompanyUserDTO.getId());
        userInfo.setPost(sysCompanyUserDTO.getPost());
        userInfo.setWorkNumber(sysCompanyUserDTO.getWorkNumber());
        userInfo.setTimeEntry(sysCompanyUserDTO.getTimeEntry());
        userInfo.setEnable(true);

        //权限集合
        List<NcAuthority> grantedAuthorities = sysCompanyUserDTO.getGrantedAuthorities();
        if(CollectionUtil.isNotEmpty(grantedAuthorities)){
            userInfo.setGrantedAuthorities(grantedAuthorities);
        }

    }

    /**
     * 判定当前员工是否是企业管理员
     * @param companyUserDTO
     * @return
     */
    private Boolean isAdmin(SysCompanyUserDTO companyUserDTO) {
        Boolean isAdmin = false;
        List<SysRoleDTO> roles = companyUserDTO.getRoles();
        if(CollectionUtil.isNotEmpty(roles)){
            for (SysRoleDTO role : roles) {
                if(role.getRoleName().startsWith(NcConstant.ADMIN_ROLE_PREFIX)){
                    isAdmin = true;
                }
            }
        }

        return isAdmin;
    }


    /**
     * 根据authType获取认证处理器
     * @return
     */
    private AuthenticationProcessor chooseAuthenticationProcessor(IntergrationAuthenticationEntity entity) {
//        Optional<AuthenticationProcessor> optional =
//                processorList.stream().filter(authenticationProcessor -> authenticationProcessor.support(entity)).findFirst();
//
//        if(optional.isPresent()){
//            return optional.get();
//        }


        for (AuthenticationProcessor processor : processorList) {
            if(processor.support(entity)){
                return processor;
            }
        }
        return null;
    }

}